package com.cd2cd.code_template.configuration;

import com.cd2cd.code_template.util.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cd2cd.code_template.configuration.constants.ServiceCode;
import com.cd2cd.code_template.configuration.exceptions.BaseRuntimeException;
import com.cd2cd.code_template.vo.BaseRes;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

import static org.springframework.http.HttpStatus.OK;

/**
 * 全局异常捕获
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionAspect {

	/**
	 * Controller 方法单独验证 数据格式验证
	 * @param e
	 * @return
	 */
	@ExceptionHandler({ConstraintViolationException.class, MissingServletRequestParameterException.class})
	@ResponseBody
	ResponseEntity<Object> methodValidatorException(Exception e){

		String errorMsg = null;
		if(e instanceof ConstraintViolationException){
			ConstraintViolationException exs = (ConstraintViolationException) e;

			StringBuilder sb = new StringBuilder();
			Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
			for (ConstraintViolation<?> item : violations) {
				sb.append(item.getPropertyPath().toString());
				sb.append(":");
				sb.append(item.getMessage());
				sb.append(",");
			}
			errorMsg = sb.toString();
		} else if( e instanceof MissingServletRequestParameterException) {
			errorMsg = e.getMessage();
		}

		BaseRes<String> res = new BaseRes<>();
		res.setServiceCode(ServiceCode.INVALID_PARAMS);

		if(StringUtils.isBlank(errorMsg)) {
			ExceptionUtils.setExceptionMsg(e, res);
		} else {
			res.setMsg(errorMsg);
		}

		return new ResponseEntity<>(res, OK);
	}
	/**
	 * 业务统一异常处理
	 * @param e
	 * @return
	 */
	@ExceptionHandler({BaseRuntimeException.class})
    @ResponseBody
    ResponseEntity<Object> baseRuntimeException(BaseRuntimeException e){

		BaseRes<String> res = new BaseRes<>();
		res.setServiceCode(e.getServiceCode());

		ExceptionUtils.setExceptionMsg(e, res);

        return new ResponseEntity<>(res, e.getHttpStatus());
    }
	
	
	/**
	 * 全局未知错误
	 * @param e
	 * @return
	 */
	@ExceptionHandler({Exception.class})
    @ResponseBody
    BaseRes<String> allException(Exception e){
		
		log.error("errorMsg={}", e.getMessage(), e);
		
		BaseRes<String> res = new BaseRes<>();
		res.setServiceCode(ServiceCode.FAILED);

		ExceptionUtils.setExceptionMsg(e, res);

        return res;
    }
	
	/**
	 * error
	 * @param e
	 * @return
	 */
	@ExceptionHandler({Error.class})
    @ResponseBody
    BaseRes<String> allError(Error e){
		
		log.error("errorMsg={}", e.getMessage(), e);
		
		BaseRes<String> res = new BaseRes<>();
		res.setServiceCode(ServiceCode.FAILED);

		ExceptionUtils.setExceptionMsg(e, res);

        return res;
    }
	
}
